﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.IO;
using System.Threading;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Runtime.InteropServices;

namespace AMStudio.Driver
{
    public class ECheck : IDisposable
    {
        protected ExceptionManager ExManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();

        public event ConnectedHandler OnConnected;
        public event ConnectClosedHandler OnConnectClosed;

        private string dllName;
        public string DllName
        {
            get { return dllName; }
            set { dllName = value; }
        }

        public bool Initialize()
        {
            bool ret = false;
            try
            {
                if (OnConnected != null)
                {
                    OnConnected(this, 0);
                }
                ret = true;
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
            }
            return ret;
        }

        public void Dispose()
        {
            Dispose(true);
            //Environment.Exit(0);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            try
            {
                int rt = FreeCanDll();
                if (OnConnectClosed != null)
                {
                    OnConnectClosed(this, rt);
                }
            }
            catch (Exception ex)
            {
                ExManager.HandleException(ex, "Policy");
            }
        }

        public void Close()
        {
            Dispose();
        }

        ~ECheck()
        {
            Dispose(false);
        }

        private void SimpleLog(string message)
        {
            LogEntry e = new LogEntry(message, "SimpleLog", 0, 0, System.Diagnostics.TraceEventType.Information, "", null);
            Logger.Write(e);
        }

        [DllImport("Kernel32.dll")]
        private extern static IntPtr LoadLibrary(String path);
        [DllImport("Kernel32.dll")]
        private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);
        [DllImport("Kernel32.dll")]
        private extern static bool FreeLibrary(IntPtr lib);

        delegate int OpenCANCard (int port);
        delegate int CloseCANCard();
        delegate int GetECU_SN(StringBuilder szSN, int iSize, StringBuilder errMsg);
        OpenCANCard openCANCard;
        CloseCANCard closeCANCard;
        GetECU_SN getECU_SN;
        private IntPtr hLib;
        public int LoadCanDll(string dllName)
        {
            hLib = LoadLibrary(dllName);
            IntPtr apiFunc = GetProcAddress(hLib, "OpenCANCard");
            if (apiFunc.ToInt32() == 0)
                return -1;
            openCANCard = (Delegate)Marshal.GetDelegateForFunctionPointer(apiFunc, typeof(OpenCANCard)) as OpenCANCard;
            apiFunc = GetProcAddress(hLib, "CloseCANCard");
            if (apiFunc.ToInt32() == 0)
                return -1;
            closeCANCard = (Delegate)Marshal.GetDelegateForFunctionPointer(apiFunc, typeof(CloseCANCard)) as CloseCANCard;
            apiFunc = GetProcAddress(hLib, "GetECU_SN");
            if (apiFunc.ToInt32() == 0)
                return -1;
            getECU_SN = (Delegate)Marshal.GetDelegateForFunctionPointer(apiFunc, typeof(GetECU_SN)) as GetECU_SN;
            return 0;
        }

        public int FreeCanDll()
        {
            if (FreeLibrary(hLib))
                return 0;
            else
                return -1;
        }

        public int GetEcuSN(out string sn, out int size, out string errMsg)
        {
            sn = string.Empty;
            errMsg = string.Empty;
            size = 512;
            StringBuilder sb = new StringBuilder(size);
            StringBuilder ms = new StringBuilder(size);
            //int ret = openCANCard(0);
            //ret = getECU_SN(sb, size, errMsg);
            //ret = closeCANCard();
            if (openCANCard(1) == -1)
                return -1;
            Thread.Sleep(800);
            if (-1 == getECU_SN(sb, size, ms))
                return -2;
            if (closeCANCard() == -1)
                return -3;
            sn = sb.ToString().Substring(0,18);
            errMsg = ms.ToString();
            return 0;
        }
    }

    public delegate void ConnectedHandler(object sender, int e);
    public delegate void ConnectClosedHandler(object sender, int e);
}
